import jwt
from django.contrib.auth import get_user_model
from django.utils.deprecation import MiddlewareMixin
from rest_framework.authentication import get_authorization_header
from rest_framework import exceptions
from django.http import JsonResponse
from rest_framework.status import HTTP_403_FORBIDDEN
from jwt.exceptions import ExpiredSignatureError
from django.contrib.auth.models import AnonymousUser
from django.shortcuts import reverse
from oaback1 import settings

OAUser = get_user_model()
class LoginCheckMiddleware(MiddlewareMixin): #定义的中间件类
    keyword = "JWT"  #JWT令牌关键字

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 对于那些不需要登录就能访问的接口，可以写在这里
        self.white_list = [reverse("oaauth:login"),reverse("staff:active_staff")]

    #中间件实例本身/当前处理的HTTP请求对象/即将被调用的视图函数/传递给视图函数的位置参数/传递给视图函数的关键字参数
    def process_view(self, request,view_func, view_args, view_kwargs):
        #这个方法在每次视图函数被调用前会被调用
        #1.如果返回None，会正常执行（包括执行视图和其他中间件代码）
        #2.如果返回HttpResponse对象那就不会执行视图和其他中间件代码（相当于拦截）

        if request.path in self.white_list or request.path.startswith(settings.MEDIA_URL):
            request.user = AnonymousUser() #将请求对象上的auth属性设置为未认证用户（django中的类）
            request.auth = None #表示不需要认证信息
            return None  #此时中间件返回None，不做拦截
        try:
            auth = get_authorization_header(request).split()  # 从请求头中提取 Authorization 字段
            # auth:['JWT','401f7ac837da42b97f613d789819ff93537bee6a']
            if not auth or auth[0].lower() != self.keyword.lower().encode():
                # 检查请求头中是否包含 Authorization 字段，并且该字段是否以 JWT 开头
                raise exceptions.ValidationError('请传入JWT！')

            if len(auth) == 1:
                msg = '不可用的JWT请求头!'
                raise exceptions.AuthenticationFailed(msg)
            elif len(auth) > 2:
                msg = "不可用的JWT请求头!中间不应存在空格！"
                raise exceptions.AuthenticationFailed(msg)

            try:  # 进行解码
                #print(auth)
                jwt_token = auth[1]

                #jwt_info = jwt.decode(auth[1], key=self.keyword.encode(), algorithms=['HS256'])
                # print(self.keyword.encode())
                # print(settings.SECRET_KEY)
                jwt_info = jwt.decode(jwt_token, settings.SECRET_KEY, algorithms=['HS256'])
                #                              key和算法必须和加密的一致
                userid = jwt_info.get("userid")  # 从解码后的 JWT 信息中提取 "userid" 键对应的值
                #print(jwt_info)
                #print(userid)

                try:
                    # 绑定当前user到request对象上
                    user = OAUser.objects.get(pk=userid)  # 使用用户 ID 从数据库中获取 OAUser 模型对象
                    #HttpResquest对象：是Django内置的
                    request.user = user  #请求对象有了一个表示当前登录用户的user属性
                    request.auth = jwt_token  #请求对象有表示用户认证信息的auth属性
                except :
                    msg = "用户不存在！"
                    raise exceptions.AuthenticationFailed(msg)
            except ExpiredSignatureError:
                msg = 'JWT Token已过期!'
                raise exceptions.AuthenticationFailed(msg)
        except Exception as e:
            print(e)
            return JsonResponse(data={"detail":"请先登录！"},status=HTTP_403_FORBIDDEN)
